home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 December / december_2000.iso / Intercd / root / Multimedia / audio / ^NoiseTracker / NtkSourceCode / Riff.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-23  |  16.0 KB  |  731 lines

  1. /*==========================================================================
  2.  
  3.      riff.cpp  -  Don Cross, April 1993.
  4.  
  5.      Contains code for reading/writing RIFF files, including .WAV files!
  6.  
  7.      See also:
  8.          ..\include\riff.h
  9.          ..\include\ddc.h
  10.  
  11.      Revision history:
  12.  
  13. 1993 April 12 [Don Cross]
  14.      Started writing this code.
  15.  
  16. 1994 October 6 [Don Cross]
  17.      Added WriteData, ReadData.
  18.      Added const modifiers to some function parameters.
  19.  
  20. 1997 September 14 [Don Cross]
  21.      Fixed a bug in WaveFile::Close.  It was calling Backpatch
  22.      and getting confused when the the file had been opened for read.
  23.      (Backpatch returns an error in that case, which prevented 
  24.      WaveFile::Close from calling RiffFile::Close.)
  25.  
  26. ==========================================================================*/
  27.  
  28. // Standard includes
  29. #include <io.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33.  
  34. // DDCLIB includes
  35. #include <riff.h>
  36.  
  37.  
  38. unsigned long FourCC ( const char *ChunkName )
  39. {
  40.    long retbuf = 0x20202020;   // four spaces (padding)
  41.    char *p = ((char *)&retbuf);
  42.  
  43.    // Remember, this is Intel format!
  44.    // The first character goes in the LSB
  45.  
  46.    for ( int i=0; i<4 && ChunkName[i]; i++ )
  47.    {
  48.       *p++ = ChunkName[i];
  49.    }
  50.  
  51.    return retbuf;
  52. }
  53.  
  54.  
  55. //----------------------------------------------------------------------
  56.  
  57.  
  58. RiffFile::RiffFile()
  59. {
  60.    file = 0;
  61.    fmode = RFM_UNKNOWN;
  62.  
  63.    riff_header.ckID = FourCC("RIFF");
  64.    riff_header.ckSize = 0;
  65. }
  66.  
  67.  
  68. RiffFile::~RiffFile()
  69. {
  70.    if ( fmode != RFM_UNKNOWN )
  71.    {
  72.       Close();
  73.    }
  74. }
  75.  
  76.  
  77. DDCRET RiffFile::Open ( const char *Filename, RiffFileMode NewMode )
  78. {
  79.    DDCRET retcode = DDC_SUCCESS;
  80.  
  81.    if ( fmode != RFM_UNKNOWN )
  82.    {
  83.       retcode = Close();
  84.    }
  85.  
  86.    if ( retcode == DDC_SUCCESS )
  87.    {
  88.       switch ( NewMode )
  89.       {
  90.          case RFM_WRITE:
  91.               file = fopen ( Filename, "wb" );
  92.               if ( file )
  93.               {
  94.                  // Write the RIFF header...
  95.                  // We will have to come back later and patch it!
  96.  
  97.                  if ( fwrite ( &riff_header, sizeof(riff_header), 1, file ) != 1 )
  98.                  {
  99.                     fclose(file);
  100.                     unlink(Filename);
  101.                     fmode = RFM_UNKNOWN;
  102.                     file = 0;
  103.                  }
  104.                  else
  105.                  {
  106.                     fmode = RFM_WRITE;
  107.                  }
  108.               }
  109.               else
  110.               {
  111.                  fmode = RFM_UNKNOWN;
  112.                  retcode = DDC_FILE_ERROR;
  113.               }
  114.               break;
  115.  
  116.          case RFM_READ:
  117.               file = fopen ( Filename, "rb" );
  118.               if ( file )
  119.               {
  120.                  // Try to read the RIFF header...
  121.  
  122.                  if ( fread ( &riff_header, sizeof(riff_header), 1, file ) != 1 )
  123.                  {
  124.                     fclose(file);
  125.                     fmode = RFM_UNKNOWN;
  126.                     file = 0;
  127.                  }
  128.                  else
  129.                  {
  130.                     fmode = RFM_READ;
  131.                  }
  132.               }
  133.               else
  134.               {
  135.                  fmode = RFM_UNKNOWN;
  136.                  retcode = DDC_FILE_ERROR;
  137.               }
  138.               break;
  139.  
  140.          default:
  141.               retcode = DDC_INVALID_CALL;
  142.       }
  143.    }
  144.  
  145.    return retcode;
  146. }
  147.  
  148.  
  149. DDCRET RiffFile::Write ( const void *Data, unsigned NumBytes )
  150. {
  151.    if ( fmode != RFM_WRITE )
  152.    {
  153.       return DDC_INVALID_CALL;
  154.    }
  155.  
  156.    if ( fwrite ( Data, NumBytes, 1, file ) != 1 )
  157.    {
  158.       return DDC_FILE_ERROR;
  159.    }
  160.  
  161.    riff_header.ckSize += NumBytes;
  162.  
  163.    return DDC_SUCCESS;
  164. }
  165.  
  166.  
  167. DDCRET RiffFile::Close()
  168. {
  169.    DDCRET retcode = DDC_SUCCESS;
  170.  
  171.    switch ( fmode )
  172.    {
  173.       case RFM_WRITE:
  174.            if ( fflush(file) ||
  175.                 fseek(file,0,SEEK_SET) ||
  176.                 fwrite ( &riff_header, sizeof(riff_header), 1, file ) != 1 ||
  177.                 fclose(file) )
  178.            {
  179.               retcode = DDC_FILE_ERROR;
  180.            }
  181.            break;
  182.  
  183.       case RFM_READ:
  184.            fclose(file);
  185.            break;
  186.    }
  187.  
  188.    file = 0;
  189.    fmode = RFM_UNKNOWN;
  190.  
  191.    return retcode;
  192. }
  193.  
  194.  
  195. long RiffFile::CurrentFilePosition() const
  196. {
  197.    return ftell ( file );
  198. }
  199.  
  200.  
  201. DDCRET RiffFile::Seek ( long offset )
  202. {
  203.    fflush ( file );
  204.  
  205.    DDCRET rc;
  206.  
  207.    if ( fseek ( file, offset, SEEK_SET ) )
  208.    {
  209.       rc = DDC_FILE_ERROR;
  210.    }
  211.    else
  212.    {
  213.       rc = DDC_SUCCESS;
  214.    }
  215.  
  216.    return rc;
  217. }
  218.  
  219.  
  220. DDCRET RiffFile::Backpatch ( long FileOffset,
  221.                              const void *Data,
  222.                              unsigned NumBytes )
  223. {
  224.    if ( !file )
  225.    {
  226.       return DDC_INVALID_CALL;
  227.    }
  228.  
  229.    if ( fflush(file) ||
  230.         fseek ( file, FileOffset, SEEK_SET ) )
  231.    {
  232.       return DDC_FILE_ERROR;
  233.    }
  234.  
  235.    return Write ( Data, NumBytes );
  236. }
  237.  
  238.  
  239. DDCRET RiffFile::Expect ( const void *Data, unsigned NumBytes )
  240. {
  241.    char *p = (char *)Data;
  242.  
  243.    while ( NumBytes-- )
  244.    {
  245.       if ( fgetc(file) != *p++ )
  246.       {
  247.          return DDC_FILE_ERROR;
  248.       }
  249.    }
  250.  
  251.    return DDC_SUCCESS;
  252. }
  253.  
  254.  
  255. DDCRET RiffFile::Read ( void *Data, unsigned NumBytes )
  256. {
  257.    DDCRET retcode = DDC_SUCCESS;
  258.  
  259.    if ( fread(Data,NumBytes,1,file) != 1 )
  260.    {
  261.       retcode = DDC_FILE_ERROR;
  262.    }
  263.  
  264.    return retcode;
  265. }
  266.  
  267.  
  268. //-----------------------------------------------------------------------
  269.  
  270. WaveFile::WaveFile()
  271. {
  272.    pcm_data.ckID = FourCC("data");
  273.    pcm_data.ckSize = 0;
  274.    num_samples = 0;
  275. }
  276.  
  277.  
  278. DDCRET WaveFile::OpenForRead ( const char *Filename )
  279. {
  280.    // Verify filename parameter as best we can...
  281.    if ( !Filename )
  282.    {
  283.       return DDC_INVALID_CALL;
  284.    }
  285.  
  286.    DDCRET retcode = Open ( Filename, RFM_READ );
  287.  
  288.    if ( retcode == DDC_SUCCESS )
  289.    {
  290.       retcode = Expect ( "WAVE", 4 );
  291.  
  292.       if ( retcode == DDC_SUCCESS )
  293.       {
  294.          retcode = Read ( &wave_format, sizeof(wave_format) );
  295.  
  296.          if ( retcode == DDC_SUCCESS &&
  297.               !wave_format.VerifyValidity() )
  298.          {
  299.             // This isn't standard PCM, so we don't know what it is!
  300.  
  301.             retcode = DDC_FILE_ERROR;
  302.          }
  303.  
  304.          if ( retcode == DDC_SUCCESS )
  305.          {
  306.             pcm_data_offset = CurrentFilePosition();
  307.  
  308.             // Figure out number of samples from
  309.             // file size, current file position, and
  310.             // WAVE header.
  311.  
  312.  
  313.  
  314.             retcode = Read ( &pcm_data, sizeof(pcm_data) );
  315.             num_samples = filelength(fileno(file)) - CurrentFilePosition();
  316.             num_samples /= NumChannels();
  317.             num_samples /= (BitsPerSample() / 8);
  318.          }
  319.       }
  320.    }
  321.  
  322.    return retcode;
  323. }
  324.  
  325.  
  326. DDCRET WaveFile::OpenForWrite ( const char  *Filename,
  327.                                 UINT32       SamplingRate,
  328.                                 UINT16       BitsPerSample,
  329.                                 UINT16       NumChannels )
  330. {
  331.    // Verify parameters...
  332.  
  333.    if ( !Filename ||
  334.         (BitsPerSample != 8 && BitsPerSample != 16) ||
  335.         NumChannels < 1 || NumChannels > 2 )
  336.    {
  337.       return DDC_INVALID_CALL;
  338.    }
  339.  
  340.    wave_format.data.Config ( SamplingRate, BitsPerSample, NumChannels );
  341.  
  342.    DDCRET retcode = Open ( Filename, RFM_WRITE );
  343.  
  344.    if ( retcode == DDC_SUCCESS )
  345.    {
  346.       retcode = Write ( "WAVE", 4 );
  347.  
  348.       if ( retcode == DDC_SUCCESS )
  349.       {
  350.          retcode = Write ( &wave_format, sizeof(wave_format) );
  351.  
  352.          if ( retcode == DDC_SUCCESS )
  353.          {
  354.             pcm_data_offset = CurrentFilePosition();
  355.             retcode = Write ( &pcm_data, sizeof(pcm_data) );
  356.          }
  357.       }
  358.    }
  359.  
  360.    return retcode;
  361. }
  362.  
  363.  
  364. DDCRET WaveFile::Close()
  365. {
  366.    DDCRET rc = DDC_SUCCESS;
  367.    
  368.    if ( fmode == RFM_WRITE )
  369.       rc = Backpatch ( pcm_data_offset, &pcm_data, sizeof(pcm_data) );
  370.  
  371.    if ( rc == DDC_SUCCESS )
  372.       rc = RiffFile::Close();
  373.  
  374.    return rc;
  375. }
  376.  
  377.  
  378. DDCRET WaveFile::WriteSample ( const INT16 Sample [MAX_WAVE_CHANNELS] )
  379. {
  380.    DDCRET retcode = DDC_SUCCESS;
  381.  
  382.    switch ( wave_format.data.nChannels )
  383.    {
  384.       case 1:
  385.            switch ( wave_format.data.nBitsPerSample )
  386.            {
  387.               case 8:
  388.                    pcm_data.ckSize += 1;
  389.                    retcode = Write ( &Sample[0], 1 );
  390.                    break;
  391.  
  392.               case 16:
  393.                    pcm_data.ckSize += 2;
  394.                    retcode = Write ( &Sample[0], 2 );
  395.                    break;
  396.  
  397.               default:
  398.                    retcode = DDC_INVALID_CALL;
  399.            }
  400.            break;
  401.  
  402.       case 2:
  403.            switch ( wave_format.data.nBitsPerSample )
  404.            {
  405.               case 8:
  406.                    retcode = Write ( &Sample[0], 1 );
  407.                    if ( retcode == DDC_SUCCESS )
  408.                    {
  409.                       retcode = Write ( &Sample[1], 1 );
  410.                       if ( retcode == DDC_SUCCESS )
  411.                       {
  412.                          pcm_data.ckSize += 2;
  413.                       }
  414.                    }
  415.                    break;
  416.  
  417.               case 16:
  418.                    retcode = Write ( &Sample[0], 2 );
  419.                    if ( retcode == DDC_SUCCESS )
  420.                    {
  421.                       retcode = Write ( &Sample[1], 2 );
  422.                       if ( retcode == DDC_SUCCESS )
  423.                       {
  424.                          pcm_data.ckSize += 4;
  425.                       }
  426.                    }
  427.                    break;
  428.  
  429.               default:
  430.                    retcode = DDC_INVALID_CALL;
  431.            }
  432.            break;
  433.  
  434.       default:
  435.            retcode = DDC_INVALID_CALL;
  436.    }
  437.  
  438.    return retcode;
  439. }
  440.  
  441.  
  442. DDCRET WaveFile::WriteMonoSample ( INT16 SampleData )
  443. {
  444.    switch ( wave_format.data.nBitsPerSample )
  445.    {
  446.       case 8:
  447.            pcm_data.ckSize += 1;
  448.            return Write ( &SampleData, 1 );
  449.  
  450.       case 16:
  451.            pcm_data.ckSize += 2;
  452.            return Write ( &SampleData, 2 );
  453.    }
  454.  
  455.    return DDC_INVALID_CALL;
  456. }
  457.  
  458.  
  459. DDCRET WaveFile::WriteStereoSample ( INT16 LeftSample,
  460.                                      INT16 RightSample )
  461. {
  462.    DDCRET retcode = DDC_SUCCESS;
  463.  
  464.    switch ( wave_format.data.nBitsPerSample )
  465.    {
  466.       case 8:
  467.            retcode = Write ( &LeftSample, 1 );
  468.            if ( retcode == DDC_SUCCESS )
  469.            {
  470.               retcode = Write ( &RightSample, 1 );
  471.               if ( retcode == DDC_SUCCESS )
  472.               {
  473.                  pcm_data.ckSize += 2;
  474.               }
  475.            }
  476.            break;
  477.  
  478.       case 16:
  479.            retcode = Write ( &LeftSample, 2 );
  480.            if ( retcode == DDC_SUCCESS )
  481.            {
  482.               retcode = Write ( &RightSample, 2 );
  483.               if ( retcode == DDC_SUCCESS )
  484.               {
  485.                  pcm_data.ckSize += 4;
  486.               }
  487.            }
  488.            break;
  489.  
  490.       default:
  491.            retcode = DDC_INVALID_CALL;
  492.    }
  493.  
  494.    return retcode;
  495. }
  496.  
  497.  
  498.  
  499. DDCRET WaveFile::ReadSample ( INT16 Sample [MAX_WAVE_CHANNELS] )
  500. {
  501.    DDCRET retcode = DDC_SUCCESS;
  502.  
  503.    switch ( wave_format.data.nChannels )
  504.    {
  505.       case 1:
  506.            switch ( wave_format.data.nBitsPerSample )
  507.            {
  508.               case 8:
  509.                    unsigned char x;
  510.                    retcode = Read ( &x, 1 );
  511.                    Sample[0] = INT16(x);
  512.                    break;
  513.  
  514.               case 16:
  515.                    retcode = Read ( &Sample[0], 2 );
  516.                    break;
  517.  
  518.               default:
  519.                    retcode = DDC_INVALID_CALL;
  520.            }
  521.            break;
  522.  
  523.       case 2:
  524.            switch ( wave_format.data.nBitsPerSample )
  525.            {
  526.               case 8:
  527.                    unsigned char  x[2];
  528.                    retcode = Read ( x, 2 );
  529.                    Sample[0] = INT16 ( x[0] );
  530.                    Sample[1] = INT16 ( x[1] );
  531.                    break;
  532.  
  533.               case 16:
  534.                    retcode = Read ( Sample, 4 );
  535.                    break;
  536.  
  537.               default:
  538.                    retcode = DDC_INVALID_CALL;
  539.            }
  540.            break;
  541.  
  542.       default:
  543.            retcode = DDC_INVALID_CALL;
  544.    }
  545.  
  546.    return retcode;
  547. }
  548.  
  549.  
  550. DDCRET WaveFile::ReadSamples ( INT32 num, WaveFileSample sarray[] )
  551. {
  552.    DDCRET retcode = DDC_SUCCESS;
  553.    INT32 i;
  554.  
  555.    switch ( wave_format.data.nChannels )
  556.    {
  557.       case 1:
  558.            switch ( wave_format.data.nBitsPerSample )
  559.            {
  560.               case 8:
  561.                    for ( i=0; i < num && retcode == DDC_SUCCESS; i++ )
  562.                    {
  563.                       unsigned char x;
  564.                       retcode = Read ( &x, 1 );
  565.                       sarray[i].chan[0] = INT16(x);
  566.                    }
  567.                    break;
  568.  
  569.               case 16:
  570.                    for ( i=0; i < num && retcode == DDC_SUCCESS; i++ )
  571.                    {
  572.                       retcode = Read ( &sarray[i].chan[0], 2 );
  573.                    }
  574.                    break;
  575.  
  576.               default:
  577.                    retcode = DDC_INVALID_CALL;
  578.            }
  579.            break;
  580.  
  581.       case 2:
  582.            switch ( wave_format.data.nBitsPerSample )
  583.            {
  584.               case 8:
  585.                    for ( i=0; i < num && retcode == DDC_SUCCESS; i++ )
  586.                    {
  587.                       unsigned char x[2];
  588.                       retcode = Read ( x, 2 );
  589.                       sarray[i].chan[0] = INT16 ( x[0] );
  590.                       sarray[i].chan[1] = INT16 ( x[1] );
  591.                    }
  592.                    break;
  593.  
  594.               case 16:
  595.                    retcode = Read ( sarray, 4 * num );
  596.                    break;
  597.  
  598.               default:
  599.                    retcode = DDC_INVALID_CALL;
  600.            }
  601.            break;
  602.  
  603.       default:
  604.            retcode = DDC_INVALID_CALL;
  605.    }
  606.  
  607.    return retcode;
  608. }
  609.  
  610.  
  611. DDCRET WaveFile::ReadMonoSample ( INT16 *Sample )
  612. {
  613.    DDCRET retcode = DDC_SUCCESS;
  614.  
  615.    switch ( wave_format.data.nBitsPerSample )
  616.    {
  617.       case 8:
  618.            unsigned char x;
  619.            retcode = Read ( &x, 1 );
  620.            *Sample = INT16(x);
  621.            break;
  622.  
  623.       case 16:
  624.            retcode = Read ( Sample, 2 );
  625.            break;
  626.  
  627.       default:
  628.            retcode = DDC_INVALID_CALL;
  629.    }
  630.  
  631.    return retcode;
  632. }
  633.  
  634.  
  635. DDCRET WaveFile::ReadStereoSample ( INT16 *L, INT16 *R )
  636. {
  637.    DDCRET retcode = DDC_SUCCESS;
  638.    UINT8          x[2];
  639.    INT16          y[2];
  640.  
  641.    switch ( wave_format.data.nBitsPerSample )
  642.    {
  643.       case 8:
  644.            retcode = Read ( x, 2 );
  645.            *L = INT16 ( x[0] );
  646.            *R = INT16 ( x[1] );
  647.            break;
  648.  
  649.       case 16:
  650.            retcode = Read ( y, 4 );
  651.            *L = INT16 ( y[0] );
  652.            *R = INT16 ( y[1] );
  653.            break;
  654.  
  655.       default:
  656.            retcode = DDC_INVALID_CALL;
  657.    }
  658.  
  659.    return retcode;
  660. }
  661.  
  662.  
  663. DDCRET WaveFile::SeekToSample ( unsigned long SampleIndex )
  664. {
  665.    if ( SampleIndex >= NumSamples() )
  666.    {
  667.       return DDC_INVALID_CALL;
  668.    }
  669.  
  670.    unsigned SampleSize = (BitsPerSample() + 7) / 8;
  671.  
  672.    DDCRET rc = Seek ( pcm_data_offset + sizeof(pcm_data) +
  673.                       SampleSize * NumChannels() * SampleIndex );
  674.  
  675.    return rc;
  676. }
  677.  
  678.  
  679. UINT32 WaveFile::SamplingRate() const
  680. {
  681.    return wave_format.data.nSamplesPerSec;
  682. }
  683.  
  684.  
  685. UINT16 WaveFile::BitsPerSample() const
  686. {
  687.    return wave_format.data.nBitsPerSample;
  688. }
  689.  
  690.  
  691. UINT16 WaveFile::NumChannels() const
  692. {
  693.    return wave_format.data.nChannels;
  694. }
  695.  
  696.  
  697. UINT32 WaveFile::NumSamples() const
  698. {
  699.    return num_samples;
  700. }
  701.  
  702.  
  703. DDCRET WaveFile::WriteData ( const INT16 *data, UINT32 numData )
  704. {
  705.     UINT32 extraBytes = numData * sizeof(INT16);
  706.     pcm_data.ckSize += extraBytes;
  707.     return RiffFile::Write ( data, extraBytes );
  708. }
  709.  
  710.  
  711. DDCRET WaveFile::WriteData ( const UINT8 *data, UINT32 numData )
  712. {
  713.     pcm_data.ckSize += numData;
  714.     return RiffFile::Write ( data, numData );
  715. }
  716.  
  717.  
  718. DDCRET WaveFile::ReadData ( INT16 *data, UINT32 numData )
  719. {
  720.     return RiffFile::Read ( data, numData * sizeof(INT16) );
  721. }
  722.  
  723.  
  724. DDCRET WaveFile::ReadData ( UINT8 *data, UINT32 numData )
  725. {
  726.     return RiffFile::Read ( data, numData );
  727. }
  728.  
  729.  
  730. /*--- end of file riff.cpp ---*/
  731.